Alex Liang

[Rails] 使用nested_form動態新增輸入欄位

實作專案ResolutionTracker時,想增加分享目標給朋友的功能。
在填入email的頁面需要動態增加輸入欄位,讓使用者一次存入多筆資料
這裡介紹nested_form解決問題

Install Gem

Gemfile
1
gem 'nested_form'

然後使用bundle install安裝並重開server

Model

我們有二個model: goal, shared_mail,分別負責處理目標和使用者存入的mail address
在goal.rb需要能接受nested_attribute

app/models/goal.rb
1
2
3
4
5
6
7
8
class Goal < ActiveRecord::Base
validates :title, presence: true

has_many :shared_mails
belongs_to :owner, class_name: "User", foreign_key: :user_id

accepts_nested_attributes_for :shared_mails, allow_destroy: true
end
app/models/shared_mail.rb
1
2
3
class SharedMail < ActiveRecord::Base
belongs_to :goal
end

Controller

controller接受strong parameter時,得允許傳入shared_mails_attribute

app/controllers/goals_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class GoalsController < ApplicationController
#略...

def create
@goal = current_user.goals.create(goal_params)

if @goal.save
redirect_to goals_path
else
render 'new'
end
end

def update
if @goal.update(goal_params)
redirect_to goal_path
else
render 'edit'
end
end

private

def goal_params
params.require(:goal).permit(:title, :comment, :is_shareable,
:complete_date,
shared_mails_attributes: [:id, :mail_addr, :_destroy])
end
end

View

view的部分,將原來的form_for(或simple_form_for)改成nested_form_for

app/views/shared_mails/new.html.erb
1
2
3
4
5
6
7
8
9
10
11
<h2>分享目標</h2>

<%= nested_form_for @goal do |f| %>
<%= f.fields_for :shared_mails do |mail_form| %>
<%= mail_form.text_field :mail_addr %>
<%= mail_form.link_to_remove "Remove this mail address" %>
<% end %>

<%= f.link_to_add "Add a mail address", :shared_mails %>
<%= f.submit "提交", disable_with: "Submiting...", class: "btn btn-primary" %>
<% end %>